# import json
# from datetime import datetime, date
# from datetime import timedelta
#
# # 获取当前日期
# today = date.today()- timedelta(days=0)
#
# # 打开文件
# with open(f'{today}.json', 'r', encoding='utf-8') as file:
#     # 加载JSON数据
#     data = json.load(file)
# # print(data)
# rankings = []
# today_solve_problems = []
# # 现在data是一个Python字典（或列表，取决于JSON的结构）
# for _ in data:
#     rankings.append(data[_])
#     today_solve_problems.append(data[_])
# # 过滤掉 'rating' 为 None 的元素
# rankings = [item for item in rankings if item['rating'] is not None]
# today_solve_problems = [item for item in today_solve_problems if item['today-solved'] != 0]
#
# # 现在可以安全排序
# rankings.sort(key=lambda x: x['rating'],reverse=True)
# today_solve_problems.sort(key=lambda x: x['today-solved'],reverse=True)
# cnt = 1
# s = ''
# for _ in rankings:
#     s += (f'{cnt}:' + _['name']+ " " + str(_['rating']))+'\n'
#     cnt += 1
# cnt = 1
# sol = ''
# for _ in today_solve_problems:
#     sol += (f'{cnt}:' + _['name']+ " " + str(_['today-solved']))+'\n'
#     cnt += 1
# # 指定文件名
# file_name1 = f"{today} rating rankings.txt"
# file_name2 = f"{today} solved rankings.txt"
#
# # 使用with语句打开文件，确保文件在操作后正确关闭
# with open(file_name1, 'w', encoding='utf-8') as file:
#     # 写入内容到文件
#       file.write(s)
# with open(file_name2, 'w', encoding='utf-8') as file:
#     # 写入内容到文件
#     file.write(sol)
#
# print("finished")

import json
from datetime import datetime, date, timedelta
import os
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import rcParams

# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS']  # 尝试两种常见中文字体
plt.rcParams['axes.unicode_minus'] = False


def generate_rankings():
    # 获取当前日期
    today = date.today() - timedelta(days=0)
    today_str = str(today)

    # 检查文件是否存在
    if not os.path.exists(f'{today_str}.json'):
        print(f"错误：文件 {today_str}.json 不存在")
        return

    # 打开文件
    with open(f'{today_str}.json', 'r', encoding='utf-8') as file:
        # 加载JSON数据
        data = json.load(file)

    # 提取所有用户数据
    all_users = list(data.values())

    # 处理rating为null的情况
    valid_ratings = []
    for user in all_users:
        if user['rating'] is not None:
            valid_ratings.append(user)
        else:
            # 为rating为null的用户设置默认值
            user['rating'] = 0
            valid_ratings.append(user)

    # 计算各种排行榜
    ratings_rankings = sorted(valid_ratings, key=lambda x: x['rating'], reverse=True)
    today_solved_rankings = sorted(all_users, key=lambda x: x['today-solved'], reverse=True)

    # 计算综合分数（rating + 今日解题数*10）
    for user in valid_ratings:
        user['composite_score'] = user['rating'] + user['today-solved'] * 10
    composite_rankings = sorted(valid_ratings, key=lambda x: x['composite_score'], reverse=True)

    # 总解题数排行榜
    total_solved_rankings = sorted(all_users, key=lambda x: x['all-solved'], reverse=True)

    # 生成文本排行榜
    generate_text_rankings(today_str, ratings_rankings, today_solved_rankings,
                           composite_rankings, total_solved_rankings)

    # 生成HTML报告
    generate_html_report(today_str, ratings_rankings, today_solved_rankings,
                         composite_rankings, total_solved_rankings)

    # 生成图表
    generate_charts(today_str, ratings_rankings, today_solved_rankings)

    # 更新历史记录
    update_history(today_str, ratings_rankings, all_users)

    print("所有报告生成完毕")


def generate_text_rankings(today, ratings, daily, composite, total):
    # 生成评分排行榜文本
    s = f'# 评分排行榜 ({today})\n\n'
    s += '排名 | 用户名 | 评分\n'
    s += '-----|--------|-----\n'
    for idx, item in enumerate(ratings[:50], 1):
        s += f'{idx} | {item["name"]} | {item["rating"]}\n'

    # 生成每日解题排行榜文本
    sol = f'# 每日解题排行榜 ({today})\n\n'
    sol += '排名 | 用户名 | 解题数\n'
    sol += '-----|--------|-------\n'
    for idx, item in enumerate(daily[:50], 1):
        # 只显示有解题记录的用户
        if item['today-solved'] > 0:
            sol += f'{idx} | {item["name"]} | {item["today-solved"]}\n'
    if sol.count('\n') < 5:  # 如果没有解题记录
        sol += "今日无解题记录\n"

    # 生成综合排行榜文本
    comp = f'# 综合排行榜 ({today})\n\n'
    comp += '排名 | 用户名 | 综合分 | 评分 | 今日解题\n'
    comp += '-----|--------|--------|------|----------\n'
    for idx, item in enumerate(composite[:50], 1):
        comp += f'{idx} | {item["name"]} | {item["composite_score"]} | {item["rating"]} | {item["today-solved"]}\n'

    # 生成总解题数排行榜文本
    total_text = f'# 总解题数排行榜 ({today})\n\n'
    total_text += '排名 | 用户名 | 总解题数\n'
    total_text += '-----|--------|----------\n'
    for idx, item in enumerate(total[:50], 1):
        total_text += f'{idx} | {item["name"]} | {item["all-solved"]}\n'

    # 写入文件
    with open(f"{today} rating rankings.txt", 'w', encoding='utf-8') as f:
        f.write(s)
    with open(f"{today} solved rankings.txt", 'w', encoding='utf-8') as f:
        f.write(sol)
    with open(f"{today} composite rankings.txt", 'w', encoding='utf-8') as f:
        f.write(comp)
    with open(f"{today} total solved rankings.txt", 'w', encoding='utf-8') as f:
        f.write(total_text)


def generate_html_report(today, ratings, daily, composite, total):
    # 创建HTML报告
    html = f'''
    <!DOCTYPE html>
    <html>
    <head>
        <title>排行榜报告 - {today}</title>
        <meta charset="UTF-8">
        <style>
            body {{ font-family: Arial, sans-serif; margin: 20px; }}
            .container {{ max-width: 1200px; margin: 0 auto; }}
            h1, h2 {{ color: #2c3e50; }}
            h1 {{ text-align: center; margin-bottom: 30px; }}
            .section {{ 
                background-color: #f9f9f9; 
                border-radius: 8px; 
                padding: 20px; 
                margin-bottom: 30px; 
                box-shadow: 0 2px 5px rgba(0,0,0,0.1);
            }}
            table {{ 
                width: 100%; 
                border-collapse: collapse; 
                margin-bottom: 20px; 
            }}
            th, td {{ 
                padding: 12px 15px; 
                text-align: left; 
                border-bottom: 1px solid #ddd; 
            }}
            th {{ 
                background-color: #3498db; 
                color: white; 
                font-weight: bold; 
            }}
            tr:hover {{ background-color: #f1f8ff; }}
            .charts {{ 
                display: flex; 
                flex-wrap: wrap; 
                justify-content: space-around; 
                margin-top: 30px;
            }}
            .chart {{ 
                width: 45%; 
                margin-bottom: 30px; 
                background: white;
                padding: 15px;
                border-radius: 8px;
                box-shadow: 0 2px 5px rgba(0,0,0,0.1);
            }}
            .chart img {{ 
                width: 100%; 
                border-radius: 4px;
            }}
            .footer {{ 
                text-align: center; 
                margin-top: 40px; 
                color: #7f8c8d; 
                font-size: 0.9em;
            }}
            .summary {{ 
                display: flex; 
                justify-content: space-around; 
                margin: 20px 0 30px 0;
                flex-wrap: wrap;
            }}
            .summary-box {{
                background: #e8f4fc;
                border-radius: 8px;
                padding: 15px;
                text-align: center;
                min-width: 200px;
                margin: 10px;
                box-shadow: 0 2px 4px rgba(0,0,0,0.05);
            }}
            .summary-value {{
                font-size: 2em;
                font-weight: bold;
                color: #2980b9;
            }}
        </style>
    </head>
    <body>
        <div class="container">
            <h1>排行榜报告 - {today}</h1>

            <div class="summary">
                <div class="summary-box">
                    <div>总用户数</div>
                    <div class="summary-value">{len(ratings)}</div>
                </div>
                <div class="summary-box">
                    <div>平均评分</div>
                    <div class="summary-value">{sum(u['rating'] for u in ratings) / len(ratings):.1f}</div>
                </div>
                <div class="summary-box">
                    <div>今日总解题</div>
                    <div class="summary-value">{sum(u['today-solved'] for u in ratings)}</div>
                </div>
                <div class="summary-box">
                    <div>最高评分</div>
                    <div class="summary-value">{max(u['rating'] for u in ratings)}</div>
                </div>
            </div>

            <div class="section">
                <h2>评分排行榜 (Top 20)</h2>
                <table>
                    <tr><th>排名</th><th>用户名</th><th>评分</th><th>历史最高</th><th>总解题数</th></tr>
    '''

    # 添加评分排行榜数据
    for idx, item in enumerate(ratings[:20], 1):
        html += f'<tr><td>{idx}</td><td>{item["name"]}</td><td>{item["rating"]}</td><td>{item.get("maxrating", "-")}</td><td>{item["all-solved"]}</td></tr>\n'
    html += '</table></div>'

    # 添加每日解题排行榜
    html += '''
            <div class="section">
                <h2>每日解题排行榜 (Top 20)</h2>
                <table>
                    <tr><th>排名</th><th>用户名</th><th>解题数</th><th>总解题数</th></tr>
    '''
    solved_count = 0
    for idx, item in enumerate(daily[:20], 1):
        if item['today-solved'] > 0:
            html += f'<tr><td>{idx}</td><td>{item["name"]}</td><td>{item["today-solved"]}</td><td>{item["all-solved"]}</td></tr>\n'
            solved_count += 1
    if solved_count == 0:
        html += '<tr><td colspan="4" style="text-align:center;">今日无解题记录</td></tr>'
    html += '</table></div>'

    # 添加综合排行榜
    html += '''
            <div class="section">
                <h2>综合排行榜 (Top 20)</h2>
                <table>
                    <tr><th>排名</th><th>用户名</th><th>综合分</th><th>评分</th><th>今日解题</th></tr>
    '''
    for idx, item in enumerate(composite[:20], 1):
        html += f'<tr><td>{idx}</td><td>{item["name"]}</td><td>{item["composite_score"]}</td><td>{item["rating"]}</td><td>{item["today-solved"]}</td></tr>\n'
    html += '</table></div>'

    # 添加总解题数排行榜
    html += '''
            <div class="section">
                <h2>总解题数排行榜 (Top 20)</h2>
                <table>
                    <tr><th>排名</th><th>用户名</th><th>总解题数</th><th>今日解题</th></tr>
    '''
    for idx, item in enumerate(total[:20], 1):
        html += f'<tr><td>{idx}</td><td>{item["name"]}</td><td>{item["all-solved"]}</td><td>{item["today-solved"]}</td></tr>\n'
    html += '</table></div>'

    # 添加图表
    html += f'''
            <div class="section">
                <h2>数据图表</h2>
                <div class="charts">
                    <div class="chart">
                        <h3>评分分布</h3>
                        <img src="{today}_rating_distribution.png" alt="评分分布图">
                    </div>
                    <div class="chart">
                        <h3>解题数分布</h3>
                        <img src="{today}_solved_distribution.png" alt="解题分布图">
                    </div>
                </div>
            </div>

            <div class="footer">
                <p>报告生成时间: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}</p>
            </div>
        </div>
    </body>
    </html>
    '''

    # 写入HTML文件
    with open(f"{today}_rankings_report.html", 'w', encoding='utf-8') as f:
        f.write(html)


def generate_charts(today, ratings, daily):
    # 生成评分分布直方图
    ratings_list = [item['rating'] for item in ratings]
    plt.figure(figsize=(10, 6))

    # 自动计算合适的bins
    max_rating = max(ratings_list)
    min_rating = min(ratings_list)
    bin_step = 50 if max_rating - min_rating > 500 else 20
    bins = range(min_rating - bin_step, max_rating + bin_step, bin_step)

    plt.hist(ratings_list, bins=bins, color='#3498db', edgecolor='black')
    plt.title('评分分布', fontsize=14)
    plt.xlabel('评分', fontsize=12)
    plt.ylabel('用户数量', fontsize=12)
    plt.grid(axis='y', alpha=0.75)
    plt.savefig(f'{today}_rating_distribution.png', bbox_inches='tight')
    plt.close()

    # 生成解题数分布直方图
    solved_list = [item['all-solved'] for item in ratings]
    plt.figure(figsize=(10, 6))

    # 自动计算合适的bins
    max_solved = max(solved_list)
    bin_step = 10 if max_solved > 100 else 5
    bins = range(0, max_solved + bin_step, bin_step)

    plt.hist(solved_list, bins=bins, color='#2ecc71', edgecolor='black')
    plt.title('总解题数分布', fontsize=14)
    plt.xlabel('解题数量', fontsize=12)
    plt.ylabel('用户数量', fontsize=12)
    plt.grid(axis='y', alpha=0.75)
    plt.savefig(f'{today}_solved_distribution.png', bbox_inches='tight')
    plt.close()

    # 生成评分与解题数关系图
    plt.figure(figsize=(10, 6))
    plt.scatter(
        [item['all-solved'] for item in ratings],
        [item['rating'] for item in ratings],
        color='#e74c3c',
        alpha=0.6
    )
    plt.title('评分与解题数关系', fontsize=14)
    plt.xlabel('总解题数', fontsize=12)
    plt.ylabel('评分', fontsize=12)
    plt.grid(True, alpha=0.3)
    plt.savefig(f'{today}_rating_vs_solved.png', bbox_inches='tight')
    plt.close()


def update_history(today, ratings, all_users):
    # 历史记录文件
    history_file = 'history.json'

    # 尝试读取历史记录
    history = {}
    if os.path.exists(history_file):
        with open(history_file, 'r', encoding='utf-8') as f:
            history = json.load(f)

    # 更新今日数据
    history[today] = {
        'date': today,
        'top_users': [item['name'] for item in ratings[:10]],
        'avg_rating': sum(item['rating'] for item in ratings) / len(ratings),
        'total_users': len(all_users),
        'active_users': sum(1 for item in all_users if item['today-solved'] > 0),
        'total_solved': sum(item['today-solved'] for item in all_users),
        'top_rating': max(item['rating'] for item in ratings),
        'top_solved': max(item['all-solved'] for item in all_users),
        'top_daily_solved': max(item['today-solved'] for item in all_users)
    }

    # 保存历史记录
    with open(history_file, 'w', encoding='utf-8') as f:
        json.dump(history, f, ensure_ascii=False, indent=2)

    # 生成历史趋势图（如果有足够数据）
    if len(history) > 1:
        generate_history_charts(history)


def generate_history_charts(history):
    # 按日期排序
    dates = sorted(history.keys())

    # 平均评分趋势图
    avg_ratings = [history[date]['avg_rating'] for date in dates]
    plt.figure(figsize=(12, 6))
    plt.plot(dates, avg_ratings, marker='o', linestyle='-', color='#3498db')
    plt.title('平均评分变化趋势', fontsize=14)
    plt.xlabel('日期', fontsize=12)
    plt.ylabel('平均评分', fontsize=12)
    plt.xticks(rotation=45)
    plt.grid(True, alpha=0.3)
    plt.tight_layout()
    plt.savefig('rating_trend.png')
    plt.close()

    # 活跃用户趋势图
    active_users = [history[date]['active_users'] for date in dates]
    plt.figure(figsize=(12, 6))
    plt.bar(dates, active_users, color='#2ecc71')
    plt.title('每日活跃用户趋势', fontsize=14)
    plt.xlabel('日期', fontsize=12)
    plt.ylabel('活跃用户数', fontsize=12)
    plt.xticks(rotation=45)
    plt.grid(axis='y', alpha=0.3)
    plt.tight_layout()
    plt.savefig('active_users_trend.png')
    plt.close()

    # 解题数趋势图
    solved_counts = [history[date]['total_solved'] for date in dates]
    plt.figure(figsize=(12, 6))
    plt.plot(dates, solved_counts, marker='o', linestyle='-', color='#e74c3c')
    plt.title('每日解题总数趋势', fontsize=14)
    plt.xlabel('日期', fontsize=12)
    plt.ylabel('解题总数', fontsize=12)
    plt.xticks(rotation=45)
    plt.grid(True, alpha=0.3)
    plt.tight_layout()
    plt.savefig('solved_trend.png')
    plt.close()


if __name__ == "__main__":
    generate_rankings()